<?php

namespace App\Services\Mission;

use App\Actions\MessageAction;
use App\Actions\PayAction;
use App\Constants\CodeData;
use App\Constants\IncomeType;
use App\Constants\MissionType;
use App\Dao\MissionConfigDao;
use App\Dao\MissionDao;
use App\Dao\UserDao;
use App\Exception\MessageException;
use App\Model\Mission;
use App\Model\MissionConfig;
use App\Utils\LoggerUtil;
use Hyperf\DbConnection\Db;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use function Hyperf\Translation\trans;

class MissionService
{
    public function __construct()
    {
    }

    /**
     * Note - 任务列表
     * DateTime 2024/8/14 11:32
     * User Admin
     * @param $uid
     * @param $sex
     * @param $language
     * @return array
     */
    public function list($uid, $sex, $language)
    {
        $list = MissionDao::getInstance()->getUserMissionList($uid, $sex);
        $time = date('Y-m-d');

        foreach ($list as $k => $v) {
            if ($v['id'] == 1207) {
                unset($list[$k]);
                continue;
            }
            if ($v['type'] == 'daily' && $v['create_time'] < $time) {
                $list[$k]['count'] = $v['status'] = 0;
            }

            $list[$k]['mission'] = trans('mission.' . $v['mission'], [], $language);
            $list[$k]['text'] = trans('mission.' . $v['text'], [], $language);
            if (mb_substr($v['extra'], -2, 2) == '金币' && mb_substr($v['extra'], 0, 2) != '最高') {
                $list[$k]['extra'] = trans('mission.金币', ['num' => $v['award_count']], $language);
            } elseif (mb_substr($v['extra'], -2, 2) == '积分') {
                $list[$k]['extra'] = trans('mission.积分', ['num' => $v['award_count']], $language);
            } else {
                $list[$k]['extra'] = trans('mission.' . $v['extra'], [], $language);
            }
            unset($list[$k]['award_count']);

        }
        $list = array_values($list);
        // Tool::JSON(\CodeData::SUCCESS, $rs);
        return formatData($list);
    }


    /**
     * Note - 领取任务奖励
     * DateTime 2024/8/14 12:01
     * User Admin
     * @param $uid
     * @param $missionId
     * @return array
     */
    public function receiveAward($uid, $missionId)
    {
        $model = MissionDao::getInstance();
        list($id, $status, $awardType, $awardCount, $maxAwardCount) = $model->getMissionStatus($uid, $missionId);
        if (empty($status) || ($status != 1)) {
            // throw new Exception('任务不可领取');
            throw new MessageException('任务不可领取', CodeData::NEED_TIPS);
        }
        try {
            Db::beginTransaction();
            $model->setMissionCompleteStatus($id);
            $extend = json_encode(['uid' => $uid, 'id' => $id, 'mission' => $missionId]);
            $userinfo = UserDao::getInstance()->findUserInfoCache($uid);
            if ($maxAwardCount > 0) {
                $awardCount = mt_rand($awardCount, $maxAwardCount);
            }
            (new PayAction())->giving_GoldOrintegrate($userinfo, $extend, $awardType, $awardCount, IncomeType::COMPLETE_TASK);
            Db::commit();
            return [];
        } catch (\Exception $e) {
            Db::rollBack();
            LoggerUtil::write('receive_award', $e->getMessage());
            throw new MessageException('领取失败', CodeData::NEED_TIPS);
        }

    }


    /**
     * Note - 任务奖励记录，用于后期发放
     * DateTime 2024/8/9 12:36
     * User Admin
     * @param $uid
     * @param $mission
     * @param $flag
     * @return bool|int
     */
    public function archiveMission($uid, $mission, $flag = null)
    {
        try {
            $time = strtotime(date('Y-m-d'));
            $current_time = date("Y-m-d H:i:s");

            Db::beginTransaction();
            // $sql = <<<SQL
            //     SELECT m.id,m.count,m.status,UNIX_TIMESTAMP(m.create_time) create_time,c.total,c.type FROM tb_mission_config c
            //     LEFT JOIN (SELECT * FROM tb_mission WHERE uid=$uid AND mission=$mission) m ON c.id=m.mission
            //     WHERE c.id=$mission
            //     ORDER BY m.id DESC
            //     LIMIT 1
            // SQL;
            $rs = MissionConfig::query()->from('tb_mission_config AS c')
                ->leftJoinSub(function ($query) use ($uid, $mission) {
                    $query->select('*')
                        ->from('tb_mission')
                        ->where('uid', $uid)
                        ->where('mission', $mission);
                }, 'm', 'c.id', '=', 'm.mission')
                ->where('c.id', $mission)
                ->select('m.id', 'm.count', 'm.status', DB::raw('UNIX_TIMESTAMP(m.create_time) as create_time'), 'c.total', 'c.type')
                ->orderByDesc('m.id')
                ->first();
            $rs = modelToArray($rs);

            if (empty($rs)) {
                throw new \Exception('任务空');
            }

            extract($rs);
            if ($type == 'daily' && $create_time < $time) {
                $rs = $id = null;
            }

            if ($mission == MissionType::MALE_PROFILE || $mission == MissionType::FEMALE_PROFILE) {
                if (empty($id)) {
                    $status = (($flag & 3) == 3) ? 1 : 0;
                    // $sql = "INSERT INTO tb_mission(uid,mission,count,status) VALUES($uid,$mission,$flag,$status)";
                    $rt = Mission::query()->insert(['uid' => $uid, 'mission' => $mission, 'count' => $flag, 'status' => $status]);
                } else {
                    $count |= $flag;
                    $status = ($status == 2) ? 2 : ((($count & 3) == 3) ? 1 : 0);
                    // $sql = "UPDATE tb_mission SET count=$count,status=$status,update_time='$current_time' WHERE id=$id";
                    $rt = Mission::query()->where('id', $id)->update(['count' => $count, 'status' => $status, 'update_time' => $current_time]);
                }
            } else if ($mission == MissionType::MALE_TOPIC) {
                if (empty($id)) {
                    // $sql = "INSERT INTO tb_mission(uid,mission,count,status) VALUES($uid,$mission,1,1)";
                    $rt = Mission::query()->insert(['uid' => $uid, 'mission' => $mission, 'count' => 1, 'status' => 1]);
                } else {
                    // $sql = "UPDATE tb_mission SET count=count+1 WHERE id=$id";
                    $rt = Mission::query()->where('id', $id)->increment('count');
                }
            } else if ($mission == MissionType::FEMALE_TOPIC) {
                if (empty($id)) {
                    // $sql = "INSERT INTO tb_mission(uid,mission,count,status) VALUES($uid,$mission,1,0)";
                    $rt = Mission::query()->insert(['uid' => $uid, 'mission' => $mission, 'count' => 1, 'status' => 0]);
                } else {
                    $count = $this->getContinousTopic($uid);
                    $status = ($status == 2) ? 2 : ($count >= 5 ? 1 : 0);
                    // $sql = "UPDATE tb_mission SET count=$count,status=$status,update_time='$current_time' WHERE id=$id";
                    $rt = Mission::query()->where('id', $id)->update(['count' => $count, 'status' => $status, 'update_time' => $current_time]);
                }
            } else if ($mission == MissionType::MALE_REPLY) {
                if (empty($id)) {
                    // $sql = "INSERT INTO tb_mission(uid,mission,count,status) VALUES($uid,$mission,1,0)";
                    $rt = Mission::query()->insert(['uid' => $uid, 'mission' => $mission, 'count' => 1, 'status' => 0]);
                } else {
                    $count = (new MessageAction())->getTodaySenderUserNum(intval($uid));
                    $status = ($status == 2) ? 2 : ($count >= 10 ? 1 : 0);
                    // $sql = "UPDATE tb_mission SET count=$count,status=$status,update_time='$current_time' WHERE id=$id";
                    $rt = Mission::query()->where('id', $id)->update(['count' => $count, 'status' => $status, 'update_time' => $current_time]);
                }
            } else if ($total > 0) {
                if (empty($id)) {
                    $status = ($total <= 1 ? 1 : 0);
                    // $sql = "INSERT INTO tb_mission(uid,mission,count,status) VALUES($uid,$mission,1,$status)";
                    $rt = Mission::query()->insert(['uid' => $uid, 'mission' => $mission, 'count' => 1, 'status' => $status]);
                } else {
                    if ($status == 0) {
                        $status = ($count >= $total - 1 ? 1 : 0);
                    }
                    // $sql = "UPDATE tb_mission SET count=count+1,status=$status,update_time='$current_time' WHERE id=$id";
                    $rt = Mission::query()->where('id', $id)->update(['status' => $status, 'update_time' => $current_time, 'count' => Db::raw("count+1")]);
                }
            } else {
                if (empty($id)) {
                    $rt = Mission::query()->insert([
                        'uid' => $uid,
                        'mission' => $mission,
                        'count' => 1,
                        'status' => 1,
                    ]);
                } else {
                    $rt = Mission::query()->where('id', $id)->update(['update_time' => $current_time, 'count' => Db::raw("count+1")]);
                }
            }
            Db::commit();
            return $rt;
        } catch (\Exception $e) {
            Db::rollBack();
            LoggerUtil::write('mission', [$e->getFile(), $e->getLine(), $e->getMessage()], 'archive_mission_error');
            return false;
        }
    }

    private function getContinousTopic($uid)
    {
        $time = strtotime(date('Y-m-d'));
        $sql = <<<SQL
            SELECT uid,MAX(count) count FROM(
                SELECT a.uid, COUNT(DISTINCT DATE_FORMAT(FROM_UNIXTIME(b.publish_time), "%Y-%m-%d")) count
                FROM tb_topic a
                INNER JOIN tb_topic b ON a.uid=b.uid AND DATEDIFF(FROM_UNIXTIME(a.publish_time),FROM_UNIXTIME(b.publish_time)) BETWEEN 0 AND 4
                WHERE a.uid=$uid AND a.publish_time>=$time
                GROUP BY a.uid,DATE_FORMAT(FROM_UNIXTIME(a.publish_time), "%Y-%m-%d")
            ) c
        SQL;

        $rs = Db::selectOne($sql);
        $rs = modelToArray($rs);
        return empty($rs) ? 0 : min($rs['count'], 5);
    }


}